<template>
  <el-form ref="tableFormRef" :model="tableForm" :show-message="showMessage" :class="{ 'hide-message': !showMessage }" @validate="onValidate">
    <el-table v-loading="loading" :data="tableForm.list" :border="border" :size="size">
      <el-table-column v-if="showIndex" type="index" label="序号" fixed="left" width="60" align="center"></el-table-column>

      <template v-for="(column, index) in columns">
        <el-table-column
          v-if="column.scopedSlots && column.scopedSlots.customRender"
          :label-class-name="column.formAttribute && column.formAttribute.required ? 'is-required' : ''"
          :key="column.key || index"
          :label="column.title"
          :width="column.width"
          :min-width="column.minWidth"
          :fixed="column.fixed"
          :show-overflow-tooltip="column.showOverflowTooltip"
        >
          <template slot-scope="scope">
            <el-form-item
              :data-prop="'list.' + scope.$index + '.' + column.dataIndex"
              :prop="'list.' + scope.$index + '.' + column.dataIndex"
              :rules="tableForm.rules[column.dataIndex]"
            >
              <slot :name="column.scopedSlots.customRender" :row="scope.row" :$index="scope.$index"></slot>
            </el-form-item>
          </template>
        </el-table-column>

        <el-table-column
          v-else
          :label-class-name="column.formAttribute && column.formAttribute.required ? 'is-required' : ''"
          :key="column.key || index"
          :prop="column.dataIndex"
          :label="column.title"
          :width="column.width"
          :min-width="column.minWidth"
          :fixed="column.fixed"
          :show-overflow-tooltip="column.showOverflowTooltip"
        >
          <template slot-scope="scope">
            <el-form-item
              :data-prop="'list.' + scope.$index + '.' + column.dataIndex"
              :prop="'list.' + scope.$index + '.' + column.dataIndex"
              :rules="tableForm.rules[column.dataIndex]"
            >
              <FormItemMiddleware
                v-if="column.formAttribute"
                :value="scope.row[column.dataIndex]"
                :field-name="column.dataIndex"
                :data-source="scope.row"
                :disabled="disabled"
                :form-attribute="column.formAttribute"
                @change="onMiddlewareChange($event, column.dataIndex, scope.row, scope.$index)"
              ></FormItemMiddleware>
              <span v-else>{{scope.row[column.dataIndex]}}</span>
            </el-form-item>

          </template>
        </el-table-column>
      </template>

      <el-table-column v-if="showAction" label="操作" :width="actionWidth" fixed="right">
        <template slot-scope="scope">
          <el-button type="primary" size="small" @click="onAdd(scope.row, scope.$index)" :disabled="disabled">添加</el-button>
          <el-button v-if="tableForm.list.length > 1" type="danger" size="small" @click="onDelete(scope.row, scope.$index)" :disabled="disabled">删除</el-button>
          <el-button v-if="isFile && scope.row[fileIdKey]" type="primary" @click="onDownload(scope.row)" size="small" :disabled="!isFile && disabled">下载</el-button>
          <base-file-upload
            v-if="isFile"
            style="margin-left: 10px; display: inline-block"
            :limit="1"
            :show-file-list="false"
            :disabled="disabled"
            @upload="onUpload($event, scope.row, scope.$index)"
          ></base-file-upload>
        </template>
      </el-table-column>

    </el-table>
  </el-form>
</template>

<script>
import _ from 'lodash';
import FormItemMiddleware from './form-item-middleware';
import { downloadFileById } from '../../apis/common-controller';

export default {
  name: 'table-form',
  components: { FormItemMiddleware },
  props: {
    loading: {
      type: Boolean,
      default: false,
    },
    dataSource: {
      type: Array,
      required: true,
    },
    columns: {
      type: Array,
      required: true,
    },
    border: {
      type: Boolean,
      default: true,
    },
    size: {
      type: String,
      default: 'small',  // medium | small | mini
    },
    // 是否显示序号
    showIndex: {
      type: Boolean,
      default: true,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    // 是否有文件
    isFile: {
      type: Boolean,
      default: false,
    },
    // 存储文件信息的字段，可以是id、fileName 等，用于判断：下载按钮仅在有文件信息时才显示
    fileIdKey: {
      type: String,
      default: 'fileIds',
    },
    // 是否显示操作项
    showAction: {
      type: Boolean,
      default: true,
    },
    // 操作项宽度
    actionWidth: {
      type: [String, Number],
      default: 200,
    },
    showMessage: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      tableForm: {
        list: [],
        rules: {},
      },
    };
  },

  watch: {
    dataSource: {
      handler(val) {
        if (val) {
          this.tableForm.list = val;
        }
      },
      immediate: true,
      deep: true,
    },

    columns: {
      handler(list) {
        list.forEach(item => {
          if (item.formAttribute) {
            if (item.formAttribute.validate) {
              this.tableForm.rules[item.dataIndex] = item.formAttribute.validate;
              item.formAttribute.required = item.formAttribute.validate.some(d => d.required);
            }
          }
        });
      },
      immediate: true,
      deep: true,
    },
  },

  methods: {
    /**
     * 中间件值改变回调事件
     * @param val
     * @param fieldName 字段名称
     * @param record  源对象
     * @param index 索引值
     */
    onMiddlewareChange(val, fieldName, record, index) {
      this.$set(this.tableForm.list[index], fieldName, val);
      this.$emit('field-change', fieldName, record, index);
    },

    /**
     * 表单校验回调函数
     */
    onValidate(fieldName, valid, message) {
      if (!this.showMessage && !valid) {
        // this.$message.error(message);
      }
    },

    /**
     * 对整个表单进行校验的方法，参数为一个回调函数。该回调函数会在校验结束后被调用，并传入两个参数：是否校验成功和未通过校验的字段。若不传入回调函数，则会返回一个 promise
     * @param callback { function(boolean, object) }
     */
    validate(callback) {
      this.$refs['tableFormRef'].validate(callback);
    },

    /**
     * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组，如不传则移除整个表单的校验结果
     * @param props { array | string }
     */
    clearValidate(props) {
      this.$refs['tableFormRef'].clearValidate(props);
    },

    /**
     * 新增
     * @param record  源对象
     * @param index 索引值
     */
    onAdd(record, index) {
      this.tableForm.list.push({});
      this.$emit('change', this.tableForm.list);
    },

    /**
     * 删除
     * @param record  源对象
     * @param index 索引值
     */
    onDelete(record, index) {
      this.$confirm('是否确定删除?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        this.tableForm.list.splice(index, 1);
        this.$emit('change', this.tableForm.list);
      }).catch(() => {});
    },

    /**
     * 文件下载
     * @param record
     */
    onDownload(record) {
      downloadFileById(record.fileId, record.name).then(() => {
        this.$message({ type: 'success', message: '文件下载成功!' });
      });
    },

    /**
     * 文件上传
     */
    onUpload(fileList, record, index) {
      const file = fileList[0];
      if (file) {
        this.$set(this.tableForm.list[index], this.fileIdKey || 'fileIds', file.fileId);
        this.$set(this.tableForm.list[index], 'fileName', file.name);
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.el-form {
  &.hide-message {
    /deep/ .el-form-item {
      padding-bottom: 0;
      margin-bottom: 0;
    }
  }
}

.el-table {
  /deep/ .el-table__header {
    th {
      .cell.is-required {
        &:before {
          content: "*";
          color: #f00;
        }
      }
    }
  }
}
</style>
